package com.tangsm.spring.boot.deferred.result.controller;

import com.tangsm.spring.boot.deferred.result.domain.vo.Result;
import com.tangsm.spring.boot.deferred.result.service.TaskService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.WebAsyncTask;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeoutException;

/**
 * WebAsyncTask异步请求调用
 *
 * @author tangsm
 */
@RestController
@RequestMapping("/task")
public class WebAsyncTaskController {
    private static final Logger logger = LoggerFactory.getLogger(WebAsyncTaskController.class);

    @Autowired
    private TaskService taskService;

    /**
     * 带超时时间的异步请求 通过WebAsyncTask自定义客户端超时间
     *
     * @return 响应结果
     */
    @GetMapping("/hello")
    public WebAsyncTask<Result<String>> hello() {
        logger.info("线程名称：{}，进入hello方法", Thread.currentThread().getName());

        // 3s钟没返回，则认为超时
        WebAsyncTask<Result<String>> webAsyncTask = new WebAsyncTask<>(3000, () -> {
            logger.info(Thread.currentThread().getName() + " 进入call方法");
            Result<String> say = taskService.getResult();
            logger.info(Thread.currentThread().getName() + " 从taskService方法返回");
            return say;
        });

        logger.info("线程名称：{}，从hello方法返回", Thread.currentThread().getName());

        // 异步请求完成时调用
        webAsyncTask.onCompletion(() -> logger.info("线程名称：{}，执行完毕", Thread.currentThread().getName()));

        // 异步请求超时时调用
        webAsyncTask.onTimeout(() -> {
            logger.info("线程名称：{}，onTimeout 调用超时", Thread.currentThread().getName());
            // 超时的时候，直接抛异常，让外层统一处理超时异常
            //throw new TimeoutException("调用超时");
            return new Result<>(0, "调用超时", "fail");
        });

        return webAsyncTask;
    }

    /**
     * 异步调用，异常处理，详细的处理流程见MyExceptionHandler类
     *
     * @return 响应结果
     */
    @GetMapping("/exception")
    public WebAsyncTask<Result<String>> exception() {
        logger.info("线程名称：{}，exception方法", Thread.currentThread().getName());
        Callable<Result<String>> callable = () -> {
            logger.info("线程名称：{}，进入call方法", Thread.currentThread().getName());
            throw new TimeoutException("调用超时!");
        };
        logger.info("线程名称：{}，从exception方法返回", Thread.currentThread().getName());
        return new WebAsyncTask<>(20000, callable);
    }
}
